/**
 * Mapping keyboard / game commands.
 */
var LEFT        = 37;
var UP          = 40;
var RIGHT       = 39;
var DOWN        = 38;
var SPACE       = 32;
var ENTER       = 13;
var RELOAD      = 82; // r
var PAUSE_START = 80; // p
var NO_WEAPON   = 48; // 0 
var WEAPON_1    = 49; // 1
var WEAPON_2    = 50; // 2 
/**
 * Frames rate.
 */
var FPS         = 30;

/**
 * The core register events, load canvas context and dual buffer, register components and 
 * configure loop game.
 * @returns {Core}
 */
Core = function()
{

    this.components = new Array();
    this.lastFrame = new Date().getTime();
    this.canvas = null;
    this.context2D = null;
    this.backBuffer = null;
    this.backBufferContext2D = null;
    this.running = false;
    
    /**
     * Initialize core.
     */
    this.run = function()
    {       
        core.registerEvents();
        core.loadDrawProperties();
        core.registerComponents();
        core.configureLoop();
        core.running = true;
    };
    
    /**
     * Registering events of keyboard or mouse.
     */
    this.registerEvents = function()
    {
        document.onkeydown = function( event )
        {
            core.keyDown( event );
        };
        document.onkeyup = function( event )
        {
            core.keyUp( event );
        };
    };

    /**
     * Load canvas and create dual buffer.
     */
    this.loadDrawProperties = function()
    {
        this.canvas = document.getElementById( 'canvas' );
        this.context2D = this.canvas.getContext( '2d' );
        
        this.backBuffer = document.createElement( 'canvas' );
        this.backBuffer.width = this.canvas.width;
        this.backBuffer.height = this.canvas.height;
        this.backBufferContext2D = this.backBuffer.getContext( '2d' );
    };

    /**
     * Registering basic components of game.
     */
    this.registerComponents = function()
    {
        var aircraft = new Aircraft( this.backBuffer.width / 2, this.backBuffer.height / 2, 1 );
        
        core.add( aircraft );
        
        core.add( new Display( aircraft, 0, 0, 0 ) );
    };

    /**
     * Set loop draw based on scenes per second.
     */
    this.configureLoop = function()
    {
        var delay = 1 / FPS;

        setInterval( function()
        {
            if ( core.running )
            {
                core.draw();
            }
        }, 
        delay );

    };
    
    /**
     * Updating and drawing registered components.
     */
    this.draw = function()
    {
        var thisFrame = new Date().getTime();
        var elapsedTime = ( thisFrame - this.lastFrame ) / 1000; // tempo desde o ultimo frame
        this.lastFrame = thisFrame;

        this.backBufferContext2D.clearRect( 0, 0, this.backBuffer.width, this.backBuffer.height );
        this.context2D.clearRect( 0, 0, this.canvas.width, this.canvas.height );

        this.updateComponents( elapsedTime, this.backBufferContext2D );

        this.drawComponents( elapsedTime, this.backBufferContext2D );
                
        this.context2D.drawImage( this.backBuffer, 0, 0 );             
    };

    /**
     * Update components, run before draw components event.
     */
    this.updateComponents = function( elapsedTime, backBufferContext2D )
    {
        for ( index in this.components )
        {
            if ( this.components[ index ].update )
            {                
                this.components[ index ].update( elapsedTime, backBufferContext2D );
            }
        }        
    };
    
    /**
     * Draw components, call draw for all components. Run after update components event.
     */
    this.drawComponents = function( elapsedTime, backBufferContext2D )
    {
        for ( index in this.components )
        {
            if ( this.components[ index ].draw )
            {
                this.backBufferContext2D.save();
                
                this.components[ index ].draw( elapsedTime, backBufferContext2D );
                
                this.backBufferContext2D.restore();
            }
        }
    };
    
    /**
     * Register component ordered by z index.
     */
    this.add = function( component )
    {
        this.components.push( component );
        this.components.sort( function( componetSelected, componentCompared )
        {
            return componetSelected.z - componentCompared.z;
        } );
    };

    /**
     * Unregister and destroy component.
     */
    this.remove = function( gameObject )
    {
        this.components.removeObject( gameObject );

        delete gameObject;
        
        gameObject = null;
    };

    /**
     * Dispatch keyDown for components.
     */
    this.keyDown = function( event )
    {
        if ( event.keyCode == PAUSE_START )
        {
            core.start();
        }
        for ( x in this.components )
        {
            if ( this.components[ x ].keyDown )
            {
                this.components[ x ].keyDown( event );
            }
        }
    };

    /**
     * Dispatch keyUp for components.
     */
    this.keyUp = function( event )
    {
        for ( x in this.components )
        {
            if ( this.components[ x ].keyUp )
            {
                this.components[ x ].keyUp( event );
            }
        }
    };

    this.start = function()
    {
       core.running = !core.running;    
    };
    
};

/**
 * Mapping keyboard / game commands.
 */
 var Key = {
	ALT: 18,
	BACKSPACE: 8,
	CAPS_LOCK: 20,
	COMMA: 188,
	COMMAND: 91,
	COMMAND_LEFT: 91, // COMMAND
	COMMAND_RIGHT: 93,
	CONTROL: 17,
	DELETE: 46,
	DOWN: 38,
	END: 35,
	ENTER: 13,
	ESCAPE: 27,
	HOME: 36,
	INSERT: 45,
	LEFT: 37,
	MENU: 93, // COMMAND_RIGHT
	NUMPAD_ADD: 107,
	NUMPAD_DECIMAL: 110,
	NUMPAD_DIVIDE: 111,
	NUMPAD_ENTER: 108,
	NUMPAD_MULTIPLY: 106,
	NUMPAD_SUBTRACT: 109,
	PAGE_DOWN: 34,
	PAGE_UP: 33,
	PERIOD: 190,
	RIGHT: 39,
	SHIFT: 16,
	SPACE: 32,
	TAB: 9,
	UP: 40,
	WINDOWS: 91, // COMMAND
	A: 65,
	B: 66,
	C: 67,
	D: 68,
	E: 69,
	F: 70,
	G: 71,
	H: 72,
	I: 73,
	J: 74,
	K: 75,
	L: 76,
	M: 77,
	N: 78,
	O: 79,
	P: 80,
	Q: 81,
	R: 82,
	S: 83,
	T: 84,
	U: 85,
	V: 86,
	W: 87,
	X: 88,
	Y: 89,
	Z: 90,
	ZERO:  48,
	ONE:   49,
	TWO:   50,
	THREE: 51,
	FOUR:  52,
	FIVE:  53,
	SIX:   54,
	SEVEN: 55,
	EIGHT: 56,
	NINE:  57
};